﻿package com.hadron.ui.scroll 
{
	import com.greensock.TweenLite;
	import com.hadron.graphics.rectangle.HadronRectangle;
	import com.hadron.ui.scroll.behaviors.IScrollBoxBehavior;
	import com.hadron.ui.scroll.behaviors.ScrollBoxBehavior;
	import flash.display.DisplayObject;
	import temple.core.CoreSprite;
	import temple.debug.IDebuggable;
	import temple.destruction.IDestructible;
	
	/**
	 * created: 2011-02-22 18:50
	 * @author Hadron
	 */
	public class ScrollBox extends CoreSprite implements IDebuggable
	{
		/*----------------------- PRIVATE -----------------------*/
		/**
		 * Flag set for debug purposes
		 * @private
		 */
		private var _debug:Boolean;
		/**
		 * Scrollbar reference
		 * @private
		 */
		private var _scrollbar:Scrollbar;
		/**
		 * Target reference
		 * @private
		 */
		private var _target:DisplayObject;
		/**
		 * Spacing between content container and scrollbar
		 * @private
		 */
		private var _spacing:Number;
		/**
		 * Transition type based on TweenLite easing functions
		 * @private
		 */
		private var _transition:Function;
		/**
		 * Time of a particular animation between move events
		 * @private
		 */
		private var _timing:Number;
		/**
		 * Original container.y position
		 * @private
		 */
		private var _originY:Number;
		/**
		 * Masking object 
		 * @private
		 */
		private var _masker:DisplayObject;
		/**
		 * Flag indicating mask should be gradient style or solid
		 * @private
		 */
		private var _gradientMask:Boolean;
		/**
		 * Behavior of component
		 * @private
		 */
		private var _scrollBehavior:IScrollBoxBehavior;
		
		/*------------------------------------------ CONSTRUCTOR --------------------------------------------*/
		public function ScrollBox(target:DisplayObject,
				thumb:DisplayObject = null,
				track:DisplayObject = null,
				masker:DisplayObject = null,
				spacing:int = 10,
				transition:Function = null,
				timing:Number = .5,
				gradientMask:Boolean = false ) 
		{
			this._target = target;
			this._spacing = spacing;
			this._transition = transition;
			this._timing = timing;
			this._masker = masker;
			this._gradientMask = gradientMask;	
			
			if (!thumb || !track)
			{
				thumb = new HadronRectangle(15, 35, 0xffffff, 1);
				track = new HadronRectangle(15, 150, 0x666666, 1);
			}
			
			//pass default parameters if there are no visual data passed
			_scrollbar = new Scrollbar(thumb, track); 
			if (!masker) 
			{
				trace('targetHeight: ' + target.height);
				_masker = new HadronRectangle(_target.width, track.height, 0xff0000, .6);
			}
			
			_target.cacheAsBitmap = true;
			addChild(_masker);
			addChild(_target);
			addChild(_scrollbar);
			
			_target.mask = this._masker;
						
			//add default vertical scroll behavior
			_scrollBehavior = new ScrollBoxBehavior(this);
		}
		
		/*------------------------------------------ PUBLIC METHODS --------------------------------------------*/
		public function fix(reset:Boolean = false):void
		{
			checkHeight();
			if (!scrollbar.visible) 
				fixPosition();
			if (reset) 
				scrollbar.resetThumbPosition(0);
			scrollbar.fixThumb(!scrollbar.visible);
		}
		
		public function resetPosition():void
		{
			//trace('scrollbar reset');
			scrollbar.resetThumbPosition();
			checkHeight();
		}
		
		/*------------------------------------------ GETTERS & SETTERS -----------------------------------------*/
		public function set target(value:DisplayObject):void { if (value) _target = value; }
		public function get target():DisplayObject { return _target; }
		public function get scrollbar():Scrollbar	{ return _scrollbar; }
		public function set spacing(value:int):void	{ _spacing = value;	}
		public function get spacing():int {	return _spacing; }
		public function set transition(value:Function):void { _transition = value;	}
		public function get transition():Function	{ return _transition; }
		public function set timing(value:Number):void { _timing = value; }
		public function get timing():Number	{ return _timing; }
		public function set gradientMask(value:Boolean):void { _gradientMask = value; }
		public function get gradientMask():Boolean { return _gradientMask; }
		public function get masker():DisplayObject { return _masker; }
		public function set debug(value:Boolean):void { _debug = value; }
		public function get debug():Boolean { return _debug; };
		public function set trackHeight(value:Number):void 
		{ 
			//set scrollbar's track height
			_scrollbar.track.height = value;
			//update scrollbar range
			_scrollbar.updateMinMax();
			//set masker height as well
			_masker.height = value;
		}
		public function get containerOriginY():Number { return _originY; }
		public function set containerOriginY(value:Number):void { _originY = value; } 
		/**
		 * Checks whether turn on/off scrollbar visibility based on masker height
		 */
		public function checkHeight():void
		{
			scrollbar.visible = (_target.height < scrollbar.height) ? false : true;
		}
		public function set scrollBehavior(behavior:IScrollBoxBehavior):void
		{
			_scrollBehavior = behavior;
		}
		
		public function get scrollBehavior():IScrollBoxBehavior
		{
			return _scrollBehavior;
		}
		
		private function fixPosition():void
		{
			if (!scrollbar.visible) 
				TweenLite.to(_target, _timing, { y: _originY, ease:_transition} );						   
		}
		
		/**
		 * Destructs object completely
		 * @inheritDoc
		 */
		override public function destruct():void
		{
			if (_target) {
				_target.y = 0;
				if (_target is IDestructible) {
					IDestructible(_target).destruct();
				} else {
					removeChild(_target);
					_target = null;
				}
			}
			if (_scrollbar) 
			{
				_scrollbar.resetThumbPosition(0);
				_scrollbar.destruct();
				_scrollbar = null;
			}
			
			if (_scrollBehavior) {
				_scrollBehavior.destruct();
				_scrollBehavior = null;
			}
			super.destruct();
		}
	}
}